#!/usr/bin/perl
# Check sync's are OK - monitoring

use Getopt::Std;
use Time::Local;

my $threshhold;
my $cur_epoch = time();
my $failcount = 0;
my @unqfs;
my %snapshots;
my %newest_snapshots;
my @zfsoutput;
my $debug = 0;

sub usage {
        print "[+] ./check_sync.pl \n";
        print "[+]\t\t -t threshhold (Time in seconds)\n";
	print "[+]\t\t -d debug output (optional)\n";
}

sub find_unqfs {
        open(ZFSLIST, "/usr/sbin/zfs get -H -p -o name,value -r creation |");
        while(<ZFSLIST>) {
                next if ($_ =~ /ROOT/);
                next unless ($_ =~ /\@/);
                push (@zfsout, $_);
                my @tmp = split('@', $_);
                push (@fs, $tmp[0]);
        }
        close (ZFSLIST);
        my %tmphash = map { $_, 1 } @fs;
        @unqfs = keys %tmphash;
}

sub find_sn {
        foreach (@zfsout) {     
                next if ($_ !~ /\@sync-/);
                ($name,$epoch) = split(/\t+/,$_);
                ($fs,$snapname) = split(/\@/,$name);
                push @{ $snapshots{$fs} }, $snapname;
        }
}

sub clean_sn {
        foreach (keys %snapshots) {     
                my $latest = pop @{$snapshots{$_}};
		chomp($latest);
                $newest_snapshots{$_} = $latest;
        }
}

sub check_sn {
        foreach (keys %newest_snapshots) {      
                my $uftime = $newest_snapshots{$_};
                if ($newest_snapshots{$_} =~ /^sync-(\d{2})(\d{2})(\d{2})(\d{2})(\d{2}).*$/) {
                        my $snaptime = timelocal(0,$5,$4,$3,$2 - 1,$1); my $snapage = ($cur_epoch - $snaptime);
                        if ($snapage > $threshold) {
				print "[+] Filesystem: $_ | Snapshot: $newest_snapshots{$_}\n" if $debug;
				print "[+]\t\tlast snapshot is " . ($snapage - $threshold) . " over $threshold\n" if $debug;
				++$failcount;
                        }
                }
        }
}

getopt('dt'); $threshold = $opt_t; $debug = $opt_d if $opt_d; if ($threshold !~ /^\d+$/ ) { usage(); print "3\n"; exit 1; }

find_unqfs;
find_sn;
clean_sn;
check_sn;

if ($failcount != 0) {
	print "1\n"; exit 0;
} else {
	print "0\n"; exit 0;
}

